package k8s

import (
	"fmt"
	"time"

	appsv1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/runtime"
	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
	"sigs.k8s.io/controller-runtime/pkg/client"
)

// Client represents a Kubernetes client with controller-runtime
type Client struct {
	client client.Client
	scheme *runtime.Scheme
	config *rest.Config
}

// ClientConfig holds configuration for the Kubernetes client
type ClientConfig struct {
	Kubeconfig string
	Namespace  string
	Timeout    time.Duration
}

// NewClient creates a new Kubernetes client
func NewClient(config *ClientConfig) (*Client, error) {
	var kubeConfig *rest.Config
	var err error

	if config.Kubeconfig != "" {
		kubeConfig, err = clientcmd.BuildConfigFromFlags("", config.Kubeconfig)
	} else {
		kubeConfig, err = rest.InClusterConfig()
	}
	if err != nil {
		return nil, fmt.Errorf("failed to get kubeconfig: %w", err)
	}

	// Set timeout if provided
	if config.Timeout > 0 {
		kubeConfig.Timeout = config.Timeout
	}

	// Create scheme and register types
	scheme := runtime.NewScheme()
	utilruntime.Must(corev1.AddToScheme(scheme))
	utilruntime.Must(appsv1.AddToScheme(scheme))

	// Create controller-runtime client
	c, err := client.New(kubeConfig, client.Options{
		Scheme: scheme,
	})
	if err != nil {
		return nil, fmt.Errorf("failed to create client: %w", err)
	}

	return &Client{
		client: c,
		scheme: scheme,
		config: kubeConfig,
	}, nil
}

// GetClient returns the underlying controller-runtime client
func (c *Client) GetClient() client.Client {
	return c.client
}

// GetScheme returns the runtime scheme
func (c *Client) GetScheme() *runtime.Scheme {
	return c.scheme
}

// GetConfig returns the rest config
func (c *Client) GetConfig() *rest.Config {
	return c.config
}
